from typing import Any, List

from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, status
from pydantic.types import UUID4
from sqlalchemy.orm import Session

from app import crud, models, schemas
from app.api import deps
from app.email_service.auth import send_new_account_email
from app.models.user import Role

router = APIRouter()


@router.get("/", response_model=List[schemas.User], summary="ADMIN: 检索用户")
def read_users(
    db: Session = Depends(deps.get_db),
    skip: int = 0,
    limit: int = 100,
    with_archived: bool = False,
    _: models.User = Depends(deps.get_current_admin_user),
) -> Any:
    """
    ADMIN: 检索用户.
    """
    users = crud.user.get_multi(db, skip=skip, limit=limit, with_archived=with_archived)
    return users


@router.post("/", response_model=schemas.User, summary="ADMIN: 创建新用户")
async def create_user(
    *,
    background_tasks: BackgroundTasks,
    db: Session = Depends(deps.get_db),
    user_in: schemas.UserCreate,
    role: Role = Role.CUSTOMER,
    _: models.User = Depends(deps.get_current_admin_user),
) -> Any:
    """
    ADMIN: 创建新用户.
    """
    user = crud.user.get_by_email(db, email=user_in.email)
    if user:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="系统中已存在具有此用户名的用户.",
        )
    user = crud.user.create(db, obj_in=user_in, role=role)
    background_tasks.add_task(send_new_account_email, email=user_in.email)
    return user


@router.put("/me", response_model=schemas.User, summary="更新当前用户")
def update_user_me(
    *,
    db: Session = Depends(deps.get_db),
    user_in: schemas.UserUpdate,
    current_user: models.User = Depends(deps.get_current_user),
) -> Any:
    """
    更新当前用户.
    """
    user = crud.user.update(db, db_obj=current_user, obj_in=user_in)
    return user


@router.get("/me", response_model=schemas.User, summary="读取当前用户")
def read_user_me(
    current_user: models.User = Depends(deps.get_current_user),
) -> Any:
    """
    读取当前用户.
    """
    return current_user


@router.delete("/me/archive", response_model=schemas.User, summary="存档当前用户")
def archive_user_me(
    db: Session = Depends(deps.get_db),
    current_user: models.User = Depends(deps.get_current_user),
) -> Any:
    """
    存档当前用户。只有管理员用户才能取消存档用户。.
    """
    user = crud.user.archive(db, obj=current_user)
    return user


@router.get("/{user_id}", response_model=schemas.User, summary="ADMID: 按 ID 读取特定用户")
def read_user(
    *,
    db: Session = Depends(deps.get_db),
    user_id: UUID4,
    current_user: models.User = Depends(deps.get_current_admin_user),
) -> Any:
    """
    ADMIN: 按 ID 读取特定用户.
    """
    user = crud.user.get(db, id=user_id, with_archived=True)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="The user with this username does not exist in the system",
        )
    if user == current_user:
        return user
    if not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="The user doesn't have enough privileges",
        )
    return user


@router.put("/{user_id}", response_model=schemas.User, summary="ADMIN: 更新用户")
def update_user(
    *,
    db: Session = Depends(deps.get_db),
    user_id: UUID4,
    user_in: schemas.UserUpdate,
    _: models.User = Depends(deps.get_current_admin_user),
) -> Any:
    """
    ADMIN: 更新用户.
    """
    user = crud.user.get(db, id=user_id, with_archived=True)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="The user with the requested id, does not exist in the system",
        )
    user = crud.user.update(db, db_obj=user, obj_in=user_in)
    return user


@router.delete("/{user_id}/archive", response_model=schemas.User, summary="ADMIN: 归档用户")
def archive_user(
    *,
    db: Session = Depends(deps.get_db),
    user_id: UUID4,
    _: models.User = Depends(deps.get_current_admin_user),
) -> Any:
    """
    ADMIN: 归档用户.
    """
    user = crud.user.get(db, id=user_id)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="The user with requested id, does not exist in the system",
        )
    user = crud.user.archive(db, user)
    return user


@router.put("/{user_id}/unarchive", response_model=schemas.User, summary="ADMIN: 取消归档用户")
def unarchive_user(
    *,
    db: Session = Depends(deps.get_db),
    user_id: UUID4,
    _: models.User = Depends(deps.get_current_admin_user),
) -> Any:
    """
    ADMIN: 取消归档用户.
    """
    user = crud.user.get(db, id=user_id, with_archived=True)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="The user with requested id, does not exist in the system",
        )
    user = crud.user.unarchive(db, user)
    return user


@router.delete("/{user_id}", response_model=schemas.User, summary="ADMIN: 永久删除用户")
def delete_user(
    *,
    db: Session = Depends(deps.get_db),
    user_id: UUID4,
    _: models.User = Depends(deps.get_current_admin_user),
) -> Any:
    """
    ADMIN: 永久删除用户.
    """
    user = crud.user.get(db, id=user_id)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="具有请求的 ID 的用户在系统中不存在",
        )
    user = crud.user.remove(db, user)
    return user


@router.post("/open", response_model=schemas.User, summary="注册新用户")
def create_user_open(
    *,
    db: Session = Depends(deps.get_db),
    user_in: schemas.UserCreate,
) -> Any:
    """
    无需登录即可创建新用户.
    """
    user = crud.user.get_by_email(db, email=user_in.email)
    if user:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="系统中已存在具有此用户名的用户.",
        )
    user = crud.user.create(db, obj_in=user_in)
    return user
